#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct WORD
{
	char bit[8]; //3 3 .5+.5 1
}WORD, * space; 

static space start_addr;
static void _set_left_link(int cur_id, int val_id);
static void _set_right_link(int cur_id, int val_id);
static void _set_tag_0(int cur_id);
static void _set_tag_1(int cur_id);
static void _set_kval(int cur_id, int kval);
static int _get_left_link(int cur_id);
static int _get_right_link(int cur_id);
static int _get_tag(int cur_id);
static int _get_kval(int cur_id);
void bit_show(int num);
void show_bit_char(char p);

#define CHUNK_MAX_CNT (1<<26)
#define FREE_LIST_NOT_AVAIL -1
int main()
{
	int i;

	start_addr=malloc(524288*1024);
	memset(start_addr, -1, 524288*1024);
	_set_kval(128,17);
	_set_right_link(128,42223828);
	_set_left_link(128,55522212);
	_set_tag_1(128);
	printf ("kval::%d\n", _get_kval(128));
	printf ("left:%d\n", _get_left_link(128));
	printf ("right:%d\n", _get_right_link(128));

//	printf ("\n");
//	for (i=0;i<8;i++) show_bit_char(start_addr[128].bit[i]);
//	printf ("\n");
//	bit_show(55522212);
//	bit_show(92223828);

	free(start_addr);
	return 0;
}


static void _set_left_link(int id, int value)
{
/*
p value: AAAABBBB -> AAAA0000 
q bit:   CCCCDDDD -> 0000DDDD 
*/
	char p,q;
	int i;

	p= (value&0x000000ff);
	start_addr[id].bit[0]=p;
	p=(value&0x0000ff00 ) >> 8;
	start_addr[id].bit[1]=p;
	p=(value&0x00ff0000 ) >> 16;
	start_addr[id].bit[2]=p;


	p=(value&0xff000000)>>24;
	p=p&0x0f;

	q=start_addr[id].bit[6];
	q=q&0xf0;

	start_addr[id].bit[6]=p | q;
}

static void _set_right_link(int id, int value)
{
/*
p value: AAAABBBB -> AAAA0000 -> 0000AAAA
q bit:   CCCCDDDD -> CCCC0000 
*/
	char p,q;
	int i;
	p= (value&0x000000ff);
	start_addr[id].bit[3]=p;
	p=(value&0x0000ff00)>>8;
	start_addr[id].bit[4]=p;
	p=(value&0x00ff0000)>>16;
	start_addr[id].bit[5]=p;

	p=(value&0xff000000)>>24;
	p=p&0x0f;
	p=p<<4;

	q=start_addr[id].bit[6];
	q=q&0x0f;
	
	start_addr[id].bit[6]=p | q;
}

static void _set_tag_0(int id)
{
/*
bit[7] p : ABCD EFGH -> ABCD EFG0
			1111 1110
*/
	int i;
	start_addr[id].bit[7]&=0x7f;
}

static void _set_tag_1(int id)
{
/*
bit[7] p : ABCD EFGH -> ABCD EFG0
			0000 0001
*/
	int i;
	start_addr[id].bit[7]|=0x80;
}

static void _set_kval(int id, int value)
{
/*
p value : CCCC CC00
bit[7] q : AAAA AAAB -> 0000 000B
*/
	int i;
	char p,q;
	p=value & 0x000000ff;
	q=start_addr[id].bit[7]&0x80;
	start_addr[id].bit[7]=p|q;
}

static int _get_left_link(int id)
{
/*
[0] [1] [2] [6.0]
bit[6] : AAAABBBB -> AAAA0000 
*/
	int result=0;
	char p;

	result=(start_addr[id].bit[6]&0x0f);
	result<<=8;
	result|=(start_addr[id].bit[2])&0xff;
	result<<=8;
	result|=(start_addr[id].bit[1])&0xff;
	result<<=8;
	p=(start_addr[id].bit[0])&0xff;
	result|=(p&0xff);
/* BUg
	result+=p;
*/

//	bit_show(result);
	if (result>=CHUNK_MAX_CNT || result<0) return FREE_LIST_NOT_AVAIL;
	return result;
}

static int _get_right_link(int id)
{
/*
[3]  [4] [5] [6.5]
bit[6] : AAAABBBB -> 0000BBBB
*/
	int result=0;
	char p;
	result=(start_addr[id].bit[6])&0xf0;
	result>>=4;
	result<<=8;
	result|=(start_addr[id].bit[5])&0xff;
	result<<=8;
	result|=(start_addr[id].bit[4])&0xff;
	result<<=8;
	result|=(start_addr[id].bit[3])&0xff;

//	bit_show(result);

	if (result>=CHUNK_MAX_CNT || result<0) return FREE_LIST_NOT_AVAIL;
	return result;
}

static int _get_tag(int id)
{
/*
[7] AAAAAAAB -> AAAAAAA0
		00000001
*/
	if ((start_addr[id].bit[7]&0x7f)==0) return 0;
	return 1;
}

static int _get_kval(int id)
{
/*
[7] AAAAAAAB -> AAAAAAA0
             -> 11111110
*/
	char p=0;
	p=start_addr[id].bit[7]&0x7f;	
	return (int)p;
}


void show_bit_char(char p)
{
	int i;
	for (i=0; i<8; i++)
		if ( (p&(1<<i)) ==0) printf ("0"); else printf ("1");
	printf (" ");
}

void bit_show(int num)
{
	int i;
	for (i=0;i<32;i++)
	{
		if ( (num&(1<<i)) ==0) printf ("0"); else printf ("1");
		if ( i%8==7 ) printf (" ");
	}
	printf ("\n");
}
